퍼스널 브랜딩 홈페이지 개발 과정
OpenClaw + Claude로 바이브코딩하여 퍼스널 브랜딩 홈페이지(ahnhyunsoo.com)를 만든 전 과정을 기록합니다. 콘텐츠 준비부터 Astro 배포, SEO/GEO 최적화까지.
이 교재에 대하여
이 교재는 AI 강사이자 컨설턴트인 안현수의 퍼스널 브랜딩 홈페이지를 처음부터 끝까지 만든 실전 사례입니다. 코드를 한 줄도 직접 치지 않고, AI(OpenClaw + Claude)에게 대화로 지시하는 바이브코딩 방식으로 개발했습니다.
단순히 "이렇게 만들었다"가 아니라, 왜 이렇게 결정했는지, 다른 방법은 무엇이 있었는지, 시행착오는 무엇이었는지를 함께 기록했습니다. 처음 홈페이지를 만드는 분도 이 교재를 따라가며 전체 흐름을 이해할 수 있습니다.
개발자가 직접 코드를 작성하는 대신, AI에게 자연어로 원하는 결과를 설명하고 AI가 코드를 생성하는 방식입니다. 이 홈페이지의 모든 HTML, CSS, JavaScript, Astro 코드는 OpenClaw를 통해 Claude가 작성했습니다.
콘텐츠 준비 및 웹페이지 개발
어떤 정보를 넣을지 정리하고, 원본 데이터를 웹에 맞게 가공하고, 페이지 구조와 디자인 시스템을 설계합니다.
1. 콘텐츠 준비
홈페이지를 만들기 전에 가장 먼저 해야 할 일은 "어떤 정보를 넣을 것인가"를 정리하는 것입니다. 디자인이나 기술보다 콘텐츠가 먼저입니다.
어떤 정보를 넣을 것인가
퍼스널 브랜딩 홈페이지에는 크게 7가지 종류의 정보가 필요했습니다.
소개 (About)
20년 경력의 이야기, 엔지니어→방법론→AI 전환 스토리
이력 & 자격
PMP, TRIZ Lv4, AICPA, 한양대 석사 등 전문 자격증
고객사
삼성, 현대 등 300+ 출강 기관 (엑셀 데이터 기반)
커리큘럼 & 교재
실제 출강 커리큘럼 11개 + 직접 제작 교재 5종
유튜브
AI 활용 강의, 바이브코딩 등 주요 영상 10개
포트폴리오
직접 만든 SaaS·앱·웹 서비스 10개
온라인 강의
gptkoreaclass.com 온라인 교육 과정 9개
About 스토리 작성 — 핵심 과정
홈페이지에서 가장 중요하면서도 어려운 부분이 자기소개 스토리였습니다. 단순한 이력서가 아니라, 방문자가 "이 사람에게 강의를 맡기고 싶다"고 느끼게 만드는 서사가 필요했습니다.
초기 문제 — "이력서 수준의 About"
첫 버전의 About 섹션은 "공학·기술경영 전공, 삼성 거침, 2013년 독립"이라는 LinkedIn 요약 수준이었습니다. 이에 대한 피드백:
스토리 구조 설계
실제 경험을 소재로 AI와 함께 스토리를 구성했습니다. 핵심은 두 번의 전환점을 중심으로 서사를 만드는 것이었습니다.
피드백을 반영한 문구 수정
스토리 초안을 작성한 뒤, 표현을 다듬는 과정을 거쳤습니다.
| 초안 | 수정 후 | 수정 이유 |
|---|---|---|
| "방법이 문제였습니다." | "열심히만 하는 것은 결코 답이 아니었습니다." | 더 직접적인 표현 |
| "더 효율적으로, 더 체계적으로" | "더 적게 일하면서도 더 높은 성과를 내는 방법" | 핵심 메시지 강조 |
| "게임이 바뀌었습니다." | "게임이 완전히 바뀌었습니다." | 강조 추가 |
| "어제도 쓴 방법" | "어제도 오늘도 제가 매일 쓰고 있는 바로 그 실무 활용 방법" | 현재진행형 강조 |
랜딩 페이지에 들어갈 짧은 소개 문구도 10개 후보를 검토한 뒤, 최종 선택:
버튼 문구: "AI를 매일 매일 쓰는 전문가의 이야기" → "자세히 보기 →"
- 홈페이지 콘텐츠는 디자인보다 먼저 준비해야 합니다
- About은 이력서가 아니라 전환점 중심의 스토리로 구성하세요
- 짧은 문구도 여러 후보를 만들고 비교해서 결정하세요
- AI가 초안을 쓰더라도, 최종 결정은 본인의 톤과 메시지로 다듬어야 합니다
2. 콘텐츠 가공
홈페이지에 넣을 정보가 정리되었으면, 다음 단계는 원본 데이터를 웹에서 사용할 수 있는 형태로 변환하는 것입니다.
엑셀 데이터 → 웹 구조로 변환
가장 대표적인 사례가 고객사 목록입니다. 원본은 레퍼런스 엑셀 파일로, I열에 강사별 표시(1)가 되어 있었습니다.
현대차(중앙일보)/부산대 → 현대자동차, 데이터랩스, C&C 삭제, 전남CEO → 전남CEO포럼. 최종 215개.
커리큘럼/교재 CMS 방식 설계
커리큘럼과 교재는 계속 추가될 예정이었기 때문에, 파일만 추가하면 자동으로 반영되는 CMS 방식이 필요했습니다.
검토된 방식들
| 방식 | 원리 | 장점 | 단점 |
|---|---|---|---|
| JSON fetch | JSON 파일을 JS로 불러옴 | 표준적 | 로컬(file://)에서 CORS 오류 |
| Notion API | 외부 서비스에서 데이터 불러옴 | 편집 편리 | 외부 서비스 의존성 |
| JS 배열 (content.js) | JavaScript 파일에 데이터 직접 기재 | 로컬에서도 동작, 단순 | 빌드 없는 정적 방식 |
채택된 방식: content.js
프로토타입 단계에서는 content.js에 JavaScript 배열로 데이터를 관리하기로 했습니다. 로컬에서 바로 열어볼 수 있어야 했기 때문입니다.
// content.js — 커리큘럼 데이터
const CURRICULUM = [
{
no: '01',
title: '교보생명 마켓센싱 AI 교육',
desc: 'AI 활용 마켓센싱 실습...',
hours: '20h',
file: 'curriculum/교보생명-마켓센싱-20h.html'
},
// file에 경로 입력 → 자동으로 "자세히 보기" 버튼 생성
];
사용 흐름은 간단합니다:
curriculum/폴더에 HTML 파일 추가content.js에 한 줄 추가 (file: 'curriculum/파일명.html')- 카드에 "자세히 보기" 버튼 자동 생성
_meta.json 파일로 대체됩니다. 빌드 타임에 JSON을 읽어서 정적 HTML로 생성하는 SSG(Static Site Generation) 방식으로 전환합니다. (Chapter 8, 13에서 상세히 다룹니다.)
다운로드 차단 — 가능할까?
커리큘럼 HTML 파일의 다운로드를 차단할 수 있는지 검토했습니다.
| 방법 | 효과 | 실제 결과 |
|---|---|---|
| 우클릭 메뉴 차단 | ⚠️ 초보자 억제 | 개발자도구로 우회 가능 |
| iframe 팝업 표시 | ⚠️ 부분적 | URL 직접 접근 시 다운 가능 |
| 서버 인증 + 워터마크 | ✅ 실질적 보호 | 서버 필요 (현재 정적 사이트) |
결론: 브라우저가 화면에 표시하려면 먼저 다운로드해야 하는 구조적 한계. 현재는 우클릭 차단 + iframe 모달(비전문가 억제 수준)을 적용하고, 배포 단계에서 서버 인증을 고려하기로 했습니다.
- 원본 데이터(엑셀)는 파싱 → 정제 → 정렬 과정을 거쳐 웹 데이터로 변환합니다
- 콘텐츠가 계속 추가되는 구조라면 CMS 방식(데이터 파일 분리)을 설계하세요
- 프로토타입에서는 단순한 방식(JS 배열)으로 시작하고, 배포 시 SSG로 전환하는 전략이 효율적입니다
- 클라이언트 측 다운로드 차단은 완벽하지 않습니다 — 진짜 보호가 필요하면 서버 인증이 필수
3. 홈페이지 구조화
5개 페이지 설계
처음에는 모든 콘텐츠를 하나의 랜딩 페이지에 넣었지만, About 스토리가 길어지면서 멀티페이지 구조로 전환했습니다.
| 방안 | 장점 | 단점 |
|---|---|---|
| A. 싱글 페이지 | 단순함 | 스크롤 과부하, SEO 불리 |
| B. 멀티 페이지 | SEO 유리, 관리 편리 | 네비게이션 필요 |
최종 5개 페이지 구조:
index.html
메인 랜딩 — Hero, About 요약, 강의 분야, 고객사, 유튜브, 문의
about.html
소개 — 스토리, 타임라인, 학력, 자격증, CTA
curriculum.html
커리큘럼 & 교재 — 11개 커리큘럼 + 5개 교재 갤러리
ai-sites.html
AI 도구들 — 33개 AI 사이트, 11개 카테고리
portfolio.html
포트폴리오 — 직접 만든 SaaS·앱·웹 10개
콘텐츠 업데이트를 고려한 구조
페이지 구조와 별도로, 콘텐츠가 지속적으로 추가될 영역(커리큘럼, 교재)은 별도의 데이터 관리 구조를 설계했습니다.
- 콘텐츠가 많으면 멀티페이지가 SEO에 유리합니다 — 각 페이지가 별도 URL로 색인됩니다
- 자주 추가되는 콘텐츠(커리큘럼, 교재)는 별도 폴더 + 데이터 파일로 분리하세요
- 구버전 백업(history/)을 습관화하면 실수 시 복구가 쉽습니다
4. 디자인 시스템
컬러 & 타이포그래피
전체 디자인 시스템의 기본 컬러는 sky blue (#0ea5e9)입니다. 전문적이면서도 신뢰감을 주는 색상으로, AI·테크 분야에 적합합니다.
컬러 팔레트
#0ea5e9
#38bdf8
#bae6fd
#1e293b
#f8fafc
타이포그래피: Pretendard Variable (한글 최적화 무료 폰트). 본문 16px, 줄간격 1.7, 제목은 weight 700~800.
컴포넌트 스타일
주요 UI 컴포넌트들의 디자인 원칙:
- 카드: 흰 배경, 얇은 border(#e2e8f0), 최소 그림자, hover 시 border 색상만 변경
- 버튼: sky blue 배경 + 흰 텍스트, hover 시 약간 어두워짐
- 칩(chip): 회색 배경, 작은 패딩, 11.5px 폰트 — 고객사 나열에 사용
- 섹션 교대: 밝음(흰) → 다크 → 밝음 패턴으로 시각적 구분
- 디자인 시스템(컬러·폰트·컴포넌트)을 먼저 정하면 일관성 있는 페이지를 빠르게 만들 수 있습니다
- 외부 브랜드 색상(유튜브 빨강 등)은 최소한만 사용하세요 — 전체 기조를 해칩니다
- Pretendard는 한글 웹사이트에 최적화된 무료 폰트입니다 (가변폰트 지원)
웹사이트 개발 및 배포
디자인 피드백을 반영하고, 기능을 구현하고, Astro로 전환하여 Vercel에 배포합니다.
5. 디자인 개선 과정
홈페이지 개발은 한 번에 완성되지 않습니다. 피드백 → 수정 → 확인의 반복이 핵심입니다. AI 바이브코딩에서도 이 사이클은 동일합니다.
피드백 → 수정 반복
Hero 섹션 변천사
Hero 섹션(첫 화면)은 여러 차례 구조가 바뀌었습니다.
| 버전 | 구조 | 문제점 / 피드백 |
|---|---|---|
| v03 | 사진(왼) + 텍스트(오) + Stats Bar | "숫자 중복 — Hero와 Stats Bar에 같은 수치" |
| v04 | 사진(왼) + 텍스트(오), Stats Bar 제거 | "사진이 너무 작다", "배경이 밋밋" |
| v05 | 텍스트 전용 센터 정렬 (이름 80px) | 사진은 About 4단 카드로 이동 |
About 섹션 변천사
고객사 chip 잔상 효과
215개 고객사를 칩으로 나열하면서, 마우스를 올렸을 때 시각적 피드백을 주기 위해 잔상 효과를 구현했습니다.
동작 원리:
mouseenter→ 즉시 네이비 배경으로 변경mouseleave→ 네이비 상태로 2초 유지- 2초 후 → 3초 linear로 원래 색상으로 페이드아웃
빠르게 고객사 목록 위를 스캔하면 마우스가 지나간 자리에 네이비 잔상이 남아 흥미로운 시각 효과를 만들어냅니다.
- 디자인은 반드시 피드백 사이클을 거칩니다 — AI 바이브코딩도 예외가 아닙니다
- 같은 정보(숫자 등)를 여러 곳에 중복 표시하면 강조 효과가 희석됩니다
- 작은 인터랙션(chip 잔상 등)이 사이트의 인상을 크게 바꿉니다
6. 기능 구현
모달 팝업 → 새 탭 전환
커리큘럼 카드를 클릭하면 처음에는 iframe 모달 팝업으로 상세 내용을 표시했습니다. 하지만 이 방식에는 문제가 있었습니다.
| 방식 | 장점 | 단점 |
|---|---|---|
| iframe 모달 팝업 | 페이지 이동 없이 확인 | SEO 불리 (iframe 안 콘텐츠 미색인), 모바일 UX 나쁨 |
| 새 탭 열기 (target="_blank") | SEO 유리, 깔끔한 UX | 페이지 이동 필요 |
SEO를 고려한 하이브리드 구조
최종적으로 <a href> + onclick 병행 구조를 채택했습니다:
<a href="curriculum/교보생명.html"
onclick="window.open(this.href,'_blank');return false;">
자세히 보기 →
</a>
- 사용자 클릭 → onclick 실행 → 새 탭 열림 (return false로 href 차단)
- 우클릭 새 탭 → href 그대로 작동
- 구글 크롤러 → href 따라가서 커리큘럼 파일도 색인
반응형 그리드
각 섹션별 반응형 브레이크포인트를 정리하면:
| 섹션 | 데스크톱 | 태블릿 (1024px↓) | 모바일 (480px↓) |
|---|---|---|---|
| About 4단 카드 | 4열 | 2열 | 1열 |
| 강의 분야 | 3열 | 2열 | 1열 |
| 유튜브 | 2열 | 2열 | 1열 |
| 온라인 강의 | 3열 | 2열 | 1열 |
- iframe 모달은 SEO에 불리합니다 — 검색엔진은 iframe 안 콘텐츠를 색인하지 않습니다
<a href> + onclick패턴으로 사용자와 크롤러 모두 대응할 수 있습니다- 반응형 디자인은 처음부터 고려해야 합니다 — 나중에 추가하면 공수가 2~3배 늘어납니다
7. 기술 선택: 왜 Astro인가?
프로토타입은 순수 HTML/CSS/JS로 만들었습니다. 하지만 배포 단계에서는 더 적합한 프레임워크가 필요했습니다.
프레임워크 비교
| 프레임워크 | 특징 | 적합성 | 판정 |
|---|---|---|---|
| 순수 HTML | 의존성 없음, 단순 | 5개 페이지에서 헤더/푸터 관리 어려움 | ❌ 프로토타입용 |
| Next.js | React 기반, SSR/SSG 지원 | 이 프로젝트에는 과잉 (React 번들 불필요) | ❌ 오버킬 |
| Hugo | Go 기반, 빠른 빌드 | Go 템플릿 문법 학습 필요 | ❌ 러닝커브 |
| Astro | 정적 우선, 제로 JS 번들, 컴포넌트 지원 | HTML 그대로 사용 + Layout 분리 + 빌드 타임 SSG | ✅ 최적 |
Astro를 선택한 이유
검토된 방법: ① 하드코딩 복붙 → ② JS fetch/include → ③ Web Components → ④ Astro/Next.js Layout
결정: "지금은 하드코딩으로 빠르게 만들고, 배포할 때 Astro로 한 번에 전환하자."
- 프로토타입은 순수 HTML로 빠르게, 배포용은 프레임워크로 전환하는 전략이 효율적입니다
- Astro는 "정적 사이트 + 컴포넌트 분리"가 필요할 때 최적의 선택입니다
- Next.js는 동적 기능(로그인, DB 등)이 필요할 때, Hugo는 Go에 익숙할 때 적합합니다
- 프레임워크 선택 기준: "이 프로젝트에 필요한 최소한의 도구가 무엇인가"
8. HTML → Astro 변환
Layout, Nav, Footer 컴포넌트 분리
Astro 프로젝트를 초기화하고 컴포넌트를 분리했습니다.
컴포넌트 구조:
Layout.astro의 핵심 구조:
---
// Layout.astro (프론트매터)
import Nav from '../components/Nav.astro';
import Footer from '../components/Footer.astro';
const { title, description } = Astro.props;
---
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>{title}</title>
<meta name="description" content={description}>
<link rel="preconnect" href="https://fonts.googleapis.com">
</head>
<body>
<Nav currentPath={Astro.url.pathname} />
<slot /> <!-- 각 페이지의 콘텐츠가 여기에 삽입됩니다 -->
<Footer />
</body>
</html>
페이지 변환 시 주의사항
HTML → Astro 변환 과정에서 만난 실제 이슈들입니다.
🐛 scrollTo 함수명 충돌
ai-sites.html에서 카테고리 이동에 scrollTo() 함수를 정의했는데, 브라우저 내장 window.scrollTo와 이름이 충돌했습니다.
해결: scrollTo → scrollToCat으로 함수명 변경.
🐛 커리큘럼 경로 중복
content.js의 file이 curriculum/파일명.html인데 JS에서 /curriculum/을 또 붙여서 경로가 이중으로 적용.
해결: href="/" + item.file 절대경로로 변경.
🐛 style vs style is:global
Astro의 <style>은 기본적으로 scoped(해당 컴포넌트에만 적용)입니다. JS로 동적 생성한 요소에는 스타일이 적용되지 않았습니다.
해결: <style is:global>로 변경하여 전역 스타일 적용.
- Astro 변환 시 가장 흔한 실수: 브라우저 내장 함수와 이름 충돌, 경로 중복, scoped 스타일
- Layout.astro의
<slot />이 핵심입니다 — 각 페이지 내용이 이 자리에 삽입됩니다 - JS로 동적 생성하는 요소에는
is:global스타일이 필요합니다
9. 배포
GitHub 리포지토리 생성
Vercel 연동
Vercel은 정적 사이트 배포에 최적화된 플랫폼입니다. GitHub 리포와 연결하면 push할 때마다 자동 배포됩니다.
커스텀 도메인 연결
Vercel이 자동 생성한 URL(site-gilt-one-13.vercel.app)은 기억하기 어렵습니다. 가비아에서 ahnhyunsoo.com 도메인을 구매하여 연결했습니다. (DNS 설정은 Chapter 13에서 상세히 다룹니다.)
- GitHub + Vercel 조합은 정적 사이트 배포의 표준입니다 — push만 하면 자동 배포
- 첫 배포는
vercel --prod수동 배포로 시작, 이후 GitHub 연동으로 자동화 - 커스텀 도메인은 사이트의 전문성을 높입니다 — 개인 브랜딩에 필수
SEO와 GEO
검색엔진 최적화(SEO)와 AI 검색 최적화(GEO)를 통해 홈페이지의 발견 가능성을 높입니다.
10. SEO/GEO 진단
사이트 전체 점검 보고서
배포 직후, 사이트 전체를 SEO/GEO 관점에서 진단했습니다. 결과는 11개 항목으로 분류됩니다.
🔴 심각 — 즉시 수정 필요
| # | 항목 | 현재 상태 | 영향 |
|---|---|---|---|
| 1 | robots.txt | 미생성 | 크롤링 범위 미명시 |
| 2 | sitemap.xml | 미생성 | 페이지 목록 전달 불가 |
| 3 | 페이지별 description | 기본값 공유 | 검색 결과 표시 불량 |
| 4 | OG + Twitter Card | 없음 | SNS 링크 미리보기 불가 |
| 5 | canonical URL | 없음 | 중복 페이지 판별 불가 |
🟡 중요 — 빠른 시일 내 수정
| # | 항목 | 현재 상태 | 영향 |
|---|---|---|---|
| 6 | JSON-LD 구조화 데이터 | 없음 | 리치 결과 미노출 |
| 7 | 커리큘럼 SSG 전환 | JS 동적 렌더링 | 크롤러가 빈 페이지로 인식 |
| 8 | 모달 잔여 코드 | 잔존 | 불필요 코드 증가 |
🟢 개선하면 좋음
| # | 항목 | 현재 상태 |
|---|---|---|
| 9 | 성능 최적화 (preconnect, preload) | 미적용 |
| 10 | 커스텀 favicon | Astro 기본값 |
| 11 | 이미지 alt 텍스트 | 일부 부족 |
우선순위별 실행 계획
| 순위 | 작업 | 예상 시간 | 효과 |
|---|---|---|---|
| 1 | robots.txt + sitemap.xml | 5분 | 🔴 크롤링 기본 |
| 2 | 페이지별 description | 10분 | 🔴 검색 결과 표시 |
| 3 | OG + Twitter Card | 15분 | 🔴 링크 미리보기 |
| 4 | canonical URL | 5분 | 🔴 중복 방지 |
| 5 | JSON-LD 구조화 데이터 | 20분 | 🟡 리치 결과 |
| 6 | 커리큘럼 SSG 전환 | 30분 | 🟡 크롤러 대응 |
| 7 | 성능 최적화 | 10분 | 🟢 웹 바이탈 |
- 배포 후 반드시 SEO/GEO 진단을 실시하세요 — 배포만으로는 검색에 노출되지 않습니다
- 심각도별로 분류하면 작업 우선순위를 객관적으로 결정할 수 있습니다
- 가장 큰 효과 대비 적은 공수: robots.txt + sitemap.xml (5분 작업)
11. 기본 SEO 설정
robots.txt + sitemap.xml
robots.txt는 검색엔진 크롤러에게 "어디를 크롤링해도 되는지" 알려주는 파일입니다. sitemap.xml은 사이트의 모든 페이지 목록을 제공합니다.
# public/robots.txt
User-agent: *
Allow: /
Sitemap: https://ahnhyunsoo.com/sitemap.xml
<!-- public/sitemap.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://ahnhyunsoo.com/</loc>
<priority>1.0</priority>
</url>
<url>
<loc>https://ahnhyunsoo.com/about</loc>
<priority>0.9</priority>
</url>
<url>
<loc>https://ahnhyunsoo.com/curriculum</loc>
<priority>0.9</priority>
</url>
<url>
<loc>https://ahnhyunsoo.com/portfolio</loc>
<priority>0.8</priority>
</url>
<url>
<loc>https://ahnhyunsoo.com/ai-sites</loc>
<priority>0.7</priority>
</url>
</urlset>
페이지별 description 설계 원칙
모든 페이지가 같은 description을 공유하고 있었습니다. 구글 검색 결과에는 이 description이 그대로 노출되기 때문에, 각 페이지별 고유한 문장이 필요합니다.
설계 원칙
- 팩트 + 숫자 중심: "300+ 기업 AI 교육" 처럼 검증 가능한 정보
- 페이지별 고유 정보: 다른 페이지와 겹치지 않는 핵심 내용
- 자연문장에 키워드 포함: 키워드 나열이 아닌 읽을 수 있는 문장
- 150자 이내: 구글이 잘라내지 않는 적정 길이
각 페이지별 description
| 페이지 | description |
|---|---|
| 홈 | ㈜알앤비디파트너스 대표 컨설턴트. 삼성전자·현대자동차 등 300+ 기업 AI 실무 교육. 20년 기술혁신 컨설팅 경력. 한국GPT협회 상임이사. |
| 소개 | 삼성그룹 자동화 엔지니어에서 시작해 20년간 PMP, TRIZ Level 4, AICPA 등을 취득하며... |
| 커리큘럼 | AI 활용 기본·심화, 바이브코딩, MS 오피스 자동화... 실제 출강 커리큘럼 11개와 직접 제작한 교재 5종 공개. |
| AI 도구들 | ChatGPT, Claude, Gemini 등 LLM부터... 강의에서 직접 사용하는 AI 사이트 30개+. |
| 포트폴리오 | 마크다운 편집기, PDF 번역기... AI와 바이브코딩으로 직접 만든 10개 서비스 모음. |
canonical URL
canonical URL은 검색엔진에게 "이 페이지의 정식 주소가 이것이다"라고 알려줍니다. www 버전과 non-www 버전이 다른 페이지로 인식되는 것을 방지합니다.
<!-- Layout.astro에서 자동 생성 -->
<link rel="canonical" href={`https://ahnhyunsoo.com${currentPath}`} />
- robots.txt + sitemap.xml은 SEO의 "입장권"입니다 — 없으면 검색 등록이 어렵습니다
- description은 구글 검색 결과에 직접 노출됩니다 — 광고 카피처럼 신중하게 작성하세요
- canonical URL로 중복 색인을 방지하세요 — www vs non-www, HTTP vs HTTPS 등
12. OG 메타태그 & 구조화 데이터
OG + Twitter Card
OG(Open Graph) 메타태그는 카카오톡, 슬랙, 텔레그램 등에서 링크를 공유할 때 미리보기 카드를 만들어줍니다. 이것이 없으면 URL 텍스트만 표시됩니다.
<!-- Layout.astro에 추가 -->
<meta property="og:title" content={title} />
<meta property="og:description" content={description} />
<meta property="og:image" content="https://ahnhyunsoo.com/og-image.jpg" />
<meta property="og:url" content={`https://ahnhyunsoo.com${currentPath}`} />
<meta property="og:locale" content="ko_KR" />
<meta property="og:site_name" content="안현수 AI 강사" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content={title} />
<meta name="twitter:description" content={description} />
<meta name="twitter:image" content="https://ahnhyunsoo.com/og-image.jpg" />
OG 이미지 디자인 과정
OG 이미지(1200×630)는 링크 공유 시 가장 먼저 보이는 요소입니다. 여러 차례 수정을 거쳤습니다.
제작 방법: og-preview.html로 디자인 → 로컬에서 확인 → Playwright로 1200×630 캡처 → og-image.jpg 저장
JSON-LD 구조화 데이터
JSON-LD는 검색엔진에게 "이 사이트가 누구의 사이트이고, 어떤 조직에 속하는지"를 기계가 읽을 수 있는 형태로 알려줍니다. 리치 결과(검색 결과에 부가 정보 표시)의 기반이 됩니다.
홈페이지에 @graph로 3개 스키마를 삽입했습니다:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@graph": [
{
"@type": "WebSite",
"name": "안현수 AI 강사",
"url": "https://ahnhyunsoo.com"
},
{
"@type": "Person",
"name": "안현수",
"alternateName": "Ahn Hyunsoo",
"jobTitle": ["AI 활용 강사", "기술혁신 컨설턴트"],
"affiliation": [
{"@type": "Organization", "name": "㈜알앤비디파트너스"},
{"@type": "Organization", "name": "한국GPT협회"}
],
"alumniOf": [
{"@type": "CollegeOrUniversity", "name": "고려대학교"},
{"@type": "CollegeOrUniversity", "name": "한양대학교 기술경영대학원"}
],
"hasCredential": ["PMP", "TRIZ Level 4", "AICPA", "CMA", "NPDP"],
"knowsAbout": ["AI", "ChatGPT", "바이브코딩", "TRIZ", "PMP",
"데이터 분석", "디지털 혁신", "노코드 자동화"],
"sameAs": [
"https://www.youtube.com/@버프TV",
"https://contents.premium.naver.com/chatgpt/buff",
"https://gptkoreaclass.com",
"https://kgpt.or.kr"
]
},
{
"@type": "Organization",
"name": "㈜알앤비디파트너스",
"url": "https://ahnhyunsoo.com"
}
]
}
</script>
- OG 메타태그는 SNS 공유의 첫인상입니다 — 반드시 설정하세요
- OG 이미지는 1200×630px이 표준입니다 — HTML로 디자인 후 캡처하면 쉽습니다
- JSON-LD는 구글의 "지식패널" 표시의 기반입니다 — Person 스키마가 가장 중요합니다
- sameAs에 공식 채널(유튜브, 네이버 등) 링크를 넣으면 검색엔진이 같은 사람으로 인식합니다
13. SSG 전환 & DNS 설정
커리큘럼 SSG 전환
가장 중요한 SEO 개선 작업 중 하나입니다. content.js로 클라이언트에서 동적으로 생성하던 커리큘럼 카드를 Astro 빌드 타임에 정적 HTML로 생성하는 방식으로 전환했습니다.
왜 SSG가 중요한가
| 방식 | 크롤러가 보는 것 | 결과 |
|---|---|---|
| JS 동적 렌더링 (content.js) | 빈 <div id="curriculum-grid"></div> |
❌ 커리큘럼 카드 0개 색인 |
| Astro SSG (빌드 타임) | 16개 카드가 모두 포함된 완성 HTML | ✅ 커리큘럼 카드 16개 색인 |
구현 방법
---
// curriculum.astro (프론트매터 — 서버 사이드)
import fs from 'node:fs';
const metaPath = './public/_meta.json';
const meta = JSON.parse(fs.readFileSync(metaPath, 'utf-8'));
const curricula = meta.curriculum;
const textbooks = meta.textbook;
---
<!-- 빌드 시점에 정적 HTML로 생성됨 -->
{curricula.map(item => (
<a href={`/curriculum/${item.file}`} class="ccl-card">
<h4>{item.title}</h4>
<p>{item.desc}</p>
<span class="hours">{item.hours}</span>
</a>
))}
이 전환 후 content.js 파일은 삭제되었습니다. 모든 데이터는 _meta.json 한 파일로 관리합니다.
DNS 설정 (가비아)
가비아에서 도메인을 구매한 후, DNS 레코드를 설정하여 Vercel과 연결했습니다.
| 타입 | 호스트 | 값 | 용도 |
|---|---|---|---|
| A | @ | 76.76.21.21 | Vercel 서버 IP |
| CNAME | www | cname.vercel-dns.com. | www 서브도메인 |
| TXT | @ | (Google 인증 코드) | Search Console 인증 |
Google Search Console 등록
마지막으로, Google Search Console에 사이트를 등록하고 sitemap.xml을 제출했습니다.
https://ahnhyunsoo.com/sitemap.xml 을 Search Console에 제출 → 5개 페이지 색인 요청성능 최적화
마지막으로 웹 성능을 높이기 위해 리소스 로딩을 최적화했습니다.
<!-- Google Fonts preconnect -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<!-- Font Awesome: preload로 렌더 블로킹 제거 -->
<link rel="preload" href="...font-awesome/all.min.css"
as="style" onload="this.onload=null;this.rel='stylesheet'">
마무리
이 교재에서는 퍼스널 브랜딩 홈페이지를 기획 → 디자인 → 개발 → 배포 → SEO/GEO 최적화까지 전 과정을 다뤘습니다.
핵심은 세 가지입니다:
- 콘텐츠가 먼저 — 기술보다 "어떤 정보를 어떻게 전달할지"가 더 중요합니다
- AI와 함께 만들기 — OpenClaw + Claude를 활용한 바이브코딩으로, 전문 개발자 없이도 프로덕션 수준의 사이트를 만들 수 있습니다
- 만든 후가 시작 — SEO, GEO, 성능 최적화는 배포 이후에 하는 것이 아니라, 처음부터 설계에 포함되어야 합니다
커리큘럼 추가, 포트폴리오 업데이트, 블로그 연동 등 —
_meta.json 수정 + git push만으로 지속적으로 업데이트되고 있습니다.실제 사이트: ahnhyunsoo.com